package logic.status;

import java.util.HashMap;
import java.util.Map;

import com.jme.math.FastMath;

import networking.messages.syncMessages.ValueType;

import main.listeners.ListenerContainer;

public abstract class StatusValueContainer<T extends ValueListener> {
	
	protected Map<ValueType, Object> data;
	protected ListenerContainer listenerContainer;
	protected float diff;
	
	public StatusValueContainer(float diff, Class<?> c) {
		this.diff = diff;
		
		data = new HashMap<ValueType, Object>();
		listenerContainer = new ListenerContainer(c);
	}
	
	public void addStatusListener(Object l) { listenerContainer.addListener(l); }
	
	public boolean removeStatusListener(Object l) { return listenerContainer.removeListener(l); }
	
	public Object getValue(ValueType type) { return data.get(type); }
	
	public float getFloatValue(ValueType type) { return ((Float)data.get(type)).floatValue(); }
	
	public int getIntValue(ValueType type) { return ((Integer)data.get(type)).intValue(); }
	
	public void changeValue(ValueType type, int value) {
		changeValue(type, Integer.valueOf(value));
	}
	
	public void changeValue(ValueType type, float value) {
		changeValue(type, Float.valueOf(value));
	}
	
	public void changeValue(ValueType type, Object value) {
		assert(type != null);
		assert(value != null);
		Object oldValue = data.get(type);
		
		if(oldValue != null) {
			boolean isFloat = oldValue instanceof Float;
			boolean isInt = oldValue instanceof Integer;
			if(isFloat || isInt) {
				float delta = 0f;
				if(isFloat) delta = ((Float)oldValue).floatValue() - ((Float)value).floatValue();
				else delta = ((Integer)oldValue).intValue() - ((Integer)value).intValue();
				delta = FastMath.abs(delta);
				
				if(delta >= diff) {
					callStatusListeners(getEvent(type, value));
					data.put(type, value);
				}
			}
		} else data.put(type, value);
	}
	
	protected void callStatusListeners(AbsChangedEvent event) {
		listenerContainer.callMethod(getListenerMethod(), event);
	}
	
	protected abstract String getListenerMethod();
	
	protected abstract AbsChangedEvent getEvent(ValueType type, Object newValue);
	
	public ListenerContainer getListenerContainer() { return listenerContainer; }
	
	public void cleanup() {
		listenerContainer.cleanUp();
		data.clear();
	}
}